﻿using Microsoft.Win32;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Security.AccessControl;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

/*********************************************************
 * 命名空间 Simple.BasicNet.Core
 * 接口名称 Container
 * 开发人员：11920
 * 创建时间：2023/4/6 11:27:04
 * 描述说明：
 * 更改历史：
 * 
 * *******************************************************/
namespace Simple.Framework.Ioc
{
    public class Container : IContainer
    {
        private static object oLock = new object();
        private static IContainer instance;
        public static IContainer SetContainer(IContainer container)
        {
            instance = container;
            return instance;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public static IContainer GetContainer()
        {
            if (instance == null)
            {
                lock (oLock)
                {
                    instance = new Container();
					builder = new ObjectBuilder(instance);
				}
			}
            return instance;
        }
        static IObjectBuilder builder;


        //接口名称对应,类名称
        /// <summary>
        /// 
        /// </summary>

        private Container()
        {
		}
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TTarget"></typeparam>
        public ITypeMapperExternal Register<TTarget>()
        {
            return Register(typeof(TTarget));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="TOriginal"></typeparam>
        /// <typeparam name="TTarget"></typeparam>
        public ITypeMapperExternal Register<TOriginal,TTarget>()
        {
            return Register(typeof(TOriginal),typeof(TTarget));
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="targetType"></param>
        public ITypeMapperExternal Register(Type targetType)
        {
            return TypeMapperExternal.Create(RegisterReturnTypeMapper(targetType));
        }
        /// <summary>
        /// 注册瞬时生命周期
        /// </summary>
        /// <param name="targetTypes"></param>
        public ITypeMapperExternal Register(Type[] targetTypes)
        {
            List<TypeMapper> typeMappers = new List<TypeMapper>();
            foreach (var item in targetTypes)
            {
                typeMappers.Add(RegisterReturnTypeMapper(item));
            }
            return TypeMapperExternal.Create(typeMappers);
        }
        /// <summary>
        /// 注册瞬时生命周期
        /// </summary>
        /// <param name="originalType"></param>
        /// <param name="targetType"></param>
        public ITypeMapperExternal Register(Type originalType, Type targetType)
        {
            return TypeMapperExternal.Create(RegisterReturnTypeMapper(originalType, targetType));
        }
        /// <summary>
        /// 注册单例
        /// </summary>
        /// <typeparam name="TTarget"></typeparam>
        public ITypeMapperExternal RegisterSingleton<TTarget>()
        {
            return RegisterSingleton(typeof(TTarget), typeof(TTarget));
        }
        /// <summary>
        /// 注册单例
        /// </summary>
        /// <typeparam name="TOriginal"></typeparam>
        /// <typeparam name="TTarget"></typeparam>
        public ITypeMapperExternal RegisterSingleton<TOriginal, TTarget>()
        {
            return RegisterSingleton(typeof(TOriginal), typeof(TTarget));
        }
        /// <summary>
        /// 注册单例
        /// </summary>
        /// <typeparam name="TTarget"></typeparam>
        /// <param name="target"></param>
        /// <returns></returns>
        public ITypeMapperExternal RegisterSingleton<TTarget>(TTarget target) where TTarget : class
        {
            TypeMapper typeMapper = new TypeMapper(target.GetType(), eLifeCycle.Single);
            Register(typeMapper);
            typeMapper.SetInstance(typeMapper.TargetKey,target);
            return TypeMapperExternal.Create(typeMapper);
        }
        /// <summary>
        /// 注册单例
        /// </summary>
        /// <param name="Target"></param>
        public ITypeMapperExternal RegisterSingleton(Type Target)
        {
            return RegisterSingleton(Target, Target);
        }
        /// <summary>
        /// 注册单例
        /// </summary>
        /// <param name="Original"></param>
        /// <param name="Target"></param>
        public ITypeMapperExternal RegisterSingleton(Type Original, Type Target)
        {
            TypeMapper typeMapper = GetTypeMapper(Original, Target);
            if (typeMapper == null)
            {
                typeMapper = new TypeMapper(Original, Target,eLifeCycle.Single);
            }
            Register(typeMapper);
            //typeMapper.SetInstance(Target.FullName, GetService(Target));
            return TypeMapperExternal.Create(typeMapper);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="original"></param>
        /// <param name="target"></param>
        public ITypeMapperExternal RegisterAssambly(Assembly original, Assembly target)
        {
            List<TypeMapper> typeMappers = new List<TypeMapper>();

			foreach (Type targetType in target.GetTypes())
			{
				var interfaces = targetType.GetInterfaces();
				Type originalInterface = null;
				foreach (var iface in interfaces.Reverse())
				{
                    if (iface.FullName != null)
                    {
						originalInterface = original.GetType(iface.FullName);
						if (originalInterface != null)
						{
							break;
						}
					}
				}
                if (originalInterface != null)
                {
					typeMappers.Add(RegisterReturnTypeMapper(originalInterface, targetType));
				}
			}
            return TypeMapperExternal.Create(typeMappers);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="IOriginal"></typeparam>
        /// <typeparam name="TTarget"></typeparam>
        /// <param name="target"></param>
        public void RegistSingletonInstance<IOriginal, TTarget>(TTarget target)
        {
            RegistSingletonInstance<IOriginal,TTarget>(target, typeof(IOriginal).FullName);
		}

		public void RegistSingletonInstance<TTarget>(TTarget target,string token)
		{
			RegistSingletonInstance<TTarget, TTarget>(target,token);
		}
		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="IOriginal"></typeparam>
		/// <typeparam name="TTarget"></typeparam>
		/// <param name="target"></param>
		/// <param name="token"></param>
		public void RegistSingletonInstance<IOriginal, TTarget>(TTarget target,string token)
		{
			Type originalType = typeof(IOriginal);
			Type targetType = typeof(TTarget);
			TypeMapper typeMapper = GetTypeMapper(originalType, targetType, target,token);
			if (typeMapper == null)
			{
				typeMapper = new TypeMapper(originalType, targetType, token,target);
			}
			Register(typeMapper);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="TTarget"></typeparam>
		/// <param name="target"></param>
		public void RegistSingletonInstance<TTarget>(TTarget target)
        {
            RegistSingletonInstance<TTarget, TTarget>(target);
        }

		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="Target"></typeparam>
		/// <returns></returns>
		public Target GetService<Target>()
        {
            return GetService<Target>(string.Empty);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="Target"></typeparam>
        /// <param name="token"></param>
        /// <returns></returns>
        public Target GetService<Target>(string token)
        {
            Type targetType = typeof(Target);
            return (Target)GetService(targetType, token);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="Target"></typeparam>
        /// <returns></returns>
        public IEnumerable<Target> GetServiceAll<Target>()
        {
            return builder.GetServiceAll<Target>();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="target"></param>
        /// <returns></returns>
        public object GetService(Type target)
        {
            return GetService(target, string.Empty);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="target"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public object GetService(Type target, string token)
        {
            return builder.GetService(target,token);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="typeMapper"></param>
        private void Register(TypeMapper typeMapper)
        {
            typeMapper.Verify();
            //string key = typeMapper.GetTypeMapperKey();
            string key = typeMapper.OriginalKey();
            if (!builder.typeMapperDic.ContainsKey(key))
            {
				builder.typeMapperDic.TryAdd(key, typeMapper);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="Original"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        private TypeMapper GetTypeMapper(Type Original, Type target)
        {
            return GetTypeMapper(Original, target, null);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="original"></param>
        /// <param name="target"></param>
        /// <param name="o"></param>
        /// <returns></returns>
        private TypeMapper GetTypeMapper(Type original, Type target, object o)
        {
            return GetTypeMapper(original,target,o,original.FullName);
		}
        /// <summary>
        /// 
        /// </summary>
        /// <param name="original"></param>
        /// <param name="target"></param>
        /// <param name="o"></param>
        /// <param name="token"></param>
        /// <returns></returns>
		private TypeMapper GetTypeMapper(Type original, Type target, object o,string token)
		{
			TypeMapper typeMapper = null;
			if (builder.typeMapperDic.ContainsKey(token))
			{
				typeMapper = builder.typeMapperDic[token];
				typeMapper.AddTarget(target, o);
			}
			return typeMapper;
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="originalType"></param>
		/// <param name="targetType"></param>
		/// <returns></returns>
		private TypeMapper RegisterReturnTypeMapper(Type originalType, Type targetType)
        {
            TypeMapper typeMapper = GetTypeMapper(originalType, targetType);
            if (typeMapper == null)
            {
                typeMapper = new TypeMapper(originalType, targetType);
            }
            Register(typeMapper);
            return typeMapper;
        }

		/// <summary>
		/// 
		/// </summary>
		/// <param name="targetType"></param>
		/// <returns></returns>
		private TypeMapper RegisterReturnTypeMapper(Type targetType)
        {
            TypeMapper typeMapper = new TypeMapper(targetType);
            Register(typeMapper);
            return typeMapper;
        }

    }
}
